#ifndef CLIENTOPERATION_H
#define CLIENTOPERATION_H

#include <QObject>
#include "seckeyshm.h"
#include "rsacrypto.h"
#include "requestcodec.h"
#include "respondcodec.h"

// 定义需要的函数指针
class ClientOperation;
// 请求之前的数据初始
typedef void (*callback1)(RequestInfo& info, RsaCrypto& rsa, ClientOperation* obj);
// 得到服务器回复之后的处理动作
typedef void (*callback2)(RespondInfo& info, ClientOperation* obj);

// communication() 的参数集合
struct ArgInfo
{
    // 数据初始化的动作
    callback1 prepare;
    // 进行数据处理的动作
    callback2 dispose;
    // ClientOperation 类型的实例对象
    ClientOperation* object;
};

// 功能类: 秘钥协商, 秘钥校验, 秘钥注销
class ClientOperation : public QObject
{
    Q_OBJECT
public:
    enum CmdType{Consult, Verify, Logout, Login};
    explicit ClientOperation(QObject *parent = nullptr);
    ~ClientOperation();
    // 秘钥协商
    // 需要传递一个 ClientOperation 类的实例对象, 通过这个对象访问类中的非静态成员变量
    static void consultPrepare(RequestInfo& info, RsaCrypto& rsa, ClientOperation* obj);
    static void consultDispose(RespondInfo& info, ClientOperation* obj);

    // 秘钥校验
    static void verifyPrepare(RequestInfo& info, RsaCrypto& rsa, ClientOperation* obj);
    static void verifyDispose(RespondInfo& info, ClientOperation* obj);

    // 秘钥注销
    static void logoutPrepare(RequestInfo& info, RsaCrypto& rsa, ClientOperation* obj);
    static void logoutDispose(RespondInfo& info, ClientOperation* obj);

    // 登录
    static void loginPrepare(RequestInfo& info, RsaCrypto& rsa, ClientOperation* obj);
    static void loginDispose(RespondInfo& info, ClientOperation* obj);


    // 完整的通信流程函数: 秘钥协商, 秘钥注销, 秘钥校验, 登录 都需要按照该流程进行数据通信
    // 精简之后这个函数需要作为实参传递到任务队列中, 这个函数的参数和返回值应该和任务队列中的任务类型保持一致
    // 根据实际需求的分析, 我们要传递两个函数指针到函数体内部, 因此只能将这两个函数指针进行封装
    // 实际的参数类型: struct ArgInfo
    static void communication(void* arg);
    // 窗口退出的时候执行的最后一个任务
    static void lastTask(void* arg);

    // 保存登录信息
    void saveLoginInfo(QString id, QString pwd);

signals:
    void showMsg(QString msg);
    void loginSuccess();
    void loginFail();

public slots:
private:
    SeckeyShm* m_shm;
    QString m_id;
    QString m_pwd;
};

#endif // CLIENTOPERATION_H
